package com.zhuhjay.service.system.service.impl;

import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhuhjay.common.base.enums.LimiterEnums;
import com.zhuhjay.common.base.exception.BasicBusinessException;
import com.zhuhjay.common.redis.util.RedisUtils;
import com.zhuhjay.common.web.model.vo.PageInfoVo;
import com.zhuhjay.service.system.mapper.SystemBlackMapper;
import com.zhuhjay.service.system.model.dto.BlackDto;
import com.zhuhjay.service.system.model.entity.SystemBlack;
import com.zhuhjay.service.system.model.entity.SystemUser;
import com.zhuhjay.service.system.service.SystemBlackService;
import com.zhuhjay.service.system.service.SystemUserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import static com.zhuhjay.common.base.constant.CacheConstant.BLACK_KEY;
import static com.zhuhjay.common.web.enums.MatchingMode.Ipv4;
import static com.zhuhjay.common.web.enums.MatchingMode.Username;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author ZhuHJay
 * @since 2023-06-17
 */
@Service
public class SystemBlackServiceImpl extends ServiceImpl<SystemBlackMapper, SystemBlack> implements SystemBlackService {

    @Resource
    private SystemUserService userService;

    @Override
    public PageInfoVo<SystemBlack> blackPage(Integer pageNum, Integer pageSize) {
        Page<SystemBlack> page = this.lambdaQuery().orderByDesc(SystemBlack::getCreateTime).page(Page.of(pageNum, pageSize));
        PageInfoVo<SystemBlack> pageInfoVo = new PageInfoVo<>();
        pageInfoVo.setTotal(page.getTotal());
        pageInfoVo.setRecords(page.getRecords());
        pageInfoVo.setCurrent(pageNum);
        pageInfoVo.setSize(pageSize);
        return pageInfoVo;
    }

    @Override
    public void add(BlackDto blackDto) {
        SystemBlack black = new SystemBlack();
        LimiterEnums type = LimiterEnums.valueOf(blackDto.getType());
        if (type == LimiterEnums.IP) {
            black.setType(LimiterEnums.IP.ordinal());
            // 判断是否是ip
            if (!ReUtil.isMatch(Ipv4.getRegular(), blackDto.getTarget())) {
                throw new BasicBusinessException(Ipv4.getMessage());
            }
        } else if (type == LimiterEnums.USER) {
            black.setType(LimiterEnums.USER.ordinal());
            // 判断是否符合用户名规则
            if (!ReUtil.isMatch(Username.getRegular(), blackDto.getTarget())) {
                throw new BasicBusinessException("用户名不符合规则");
            }
            // 判断是否存在该用户
            userService.lambdaQuery().eq(SystemUser::getUsername, blackDto.getTarget())
                    .oneOpt().orElseThrow(() -> new BasicBusinessException("用户不存在"));
        }
        black.setTarget(blackDto.getTarget());
        black.setReason("管理员手动拉黑");
        this.save(black);
        // 添加到黑名单中
        RedisUtils.addValue2Set(BLACK_KEY, blackDto.getTarget());
    }

    @Override
    public void addBlack4Limiter(LimiterEnums type, String target, String reason) {
        SystemBlack black = new SystemBlack();
        black.setType(type.ordinal());
        black.setTarget(target);
        black.setReason(StrUtil.format("限流器自动拉黑: {}", reason));
        this.save(black);
        // 添加到黑名单中
        RedisUtils.addValue2Set(BLACK_KEY, target);
    }

}
